package xin.petstore.framework.exception;

import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.NoSuchMessageException;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import org.springframework.web.util.WebUtils;

public class SimpleHandlerExceptionResolver extends AbstractHandlerExceptionResolver
        implements MessageSourceAware {
    private MessageSource messageSource;
    public static final String DEFAULT_EXCEPTION_ATTRIBUTE = "exception";
    private String defaultErrorView;
    private Integer defaultStatusCode = Integer.valueOf(200);

    private String exceptionAttribute = "exception";

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        applyStatusCodeIfPossible(request, response, this.defaultStatusCode.intValue());

        return getModelAndView(request, this.defaultErrorView, ex);
    }

    @Override
    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    protected void applyStatusCodeIfPossible(HttpServletRequest request, HttpServletResponse response, int statusCode) {
        if (!WebUtils.isIncludeRequest(request)) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Applying HTTP status code " + statusCode);
            }
            response.setStatus(statusCode);
            request.setAttribute("javax.servlet.error.status_code", Integer.valueOf(statusCode));
        }
    }

    protected ModelAndView getModelAndView(HttpServletRequest request, String viewName, Exception ex) {
        ModelAndView mv = new ModelAndView(viewName);

        if (this.exceptionAttribute != null) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Exposing Exception as model attribute '" + this.exceptionAttribute + "'");
            }
            String msg = null;
            try {
                String cn = ex.getClass().getSimpleName();
                if (this.logger.isErrorEnabled()) {
                    this.logger.error(cn + " error \n", ex);
                }
                msg = ex.getMessage();
                if ((!StringUtils.isEmpty(msg)) && (msg.startsWith("${")))
                    msg = this.messageSource.getMessage(msg.substring(2, msg.length() - 1), null, Locale.ROOT);
                else {
                    msg = this.messageSource.getMessage(this.exceptionAttribute + "." + cn + ".msg", null, Locale.ROOT);
                }
            } catch (NoSuchMessageException localNoSuchMessageException) {
            }
            if (((request.getContentType() != null) && (request.getContentType().equalsIgnoreCase("application/json"))) || ((request.getHeader("Accept") != null) && (request.getHeader("Accept").contains("application/json")))) {
                MappingJackson2JsonView view = new MappingJackson2JsonView();
                view.addStaticAttribute(this.exceptionAttribute, msg);
                mv.setView(view);
            } else {
                mv.addObject(this.exceptionAttribute, msg);
            }
        }

        return mv;
    }

    public void setDefaultErrorView(String defaultErrorView) {
        this.defaultErrorView = defaultErrorView;
    }

    public void setDefaultStatusCode(Integer defaultStatusCode) {
        this.defaultStatusCode = defaultStatusCode;
    }
}

